
/*    This file is part of the Managarm operating system.
 *   Copyright (C) 2007, 2008, 2009  Alexander van der Grinten
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. */

package org.managarm.jmanacclib.core;

public abstract class CclibWriter {
	public static final class BufferWriter extends CclibWriter {
		private final class BufferReader extends CclibReader {
			private SourceList pointer;
			private CclibSource source;
			private int offset = 0;
			private int line = 0;
			
			public BufferReader() {
				pointer = sourceHead;
				
				updateSource(); // get the first source object
			}
			
			private final void updateSource() {
				while(pointer != null) {
					if(pointer.character > offset)
						return;
					source = pointer.source;
					line = 0; // reset the relative line counter
					pointer = pointer.successor; // move to the next object
				}
			}
			
			// implementation of abstract methods
			@Override public boolean endReached() {
				return offset == buffer.length();
			}
			@Override public char fetch() {
				final char c = buffer.charAt(offset);
				offset++;
				updateSource(); // update the source pointer
				if(c == '\n')
					line++; // increment the relative line counter
				return c;
			}
			@Override public CclibSource getSource() {
				return source;
			}
			@Override public int getDisplacement() {
				return line;
			}
		}
		
		private static final class SourceList {
			public final int character;
			public final CclibSource source;
			public SourceList successor;
			
			public SourceList(int character, CclibSource source) {
				this.character = character;
				this.source = source;
			}
		}
		
		private final StringBuffer buffer = new StringBuffer();
		private SourceList sourceHead;
		private SourceList sourceTail;
		
		public CclibReader makeReader() {
			return new BufferReader();
		}
		
		// implementation of abstract methods
		@Override public void emit(char c) {
			buffer.append(c);
		}
		@Override public void locate(CclibSource source) {
			final int off = buffer.length();
			final SourceList entry = new SourceList(off, source);
			if(sourceHead == null) {
				sourceHead = entry;
				sourceTail = entry;
			}else{
				sourceTail.successor = entry;
				sourceTail = entry;
			}
		}
	}
	
	public abstract void emit(char c);
	public abstract void locate(CclibSource source);
	
	
	public final void emit(char c, CclibSource source) {
		locate(source); emit(c);
	}
	public final void emit(String s) {
		for(int i = 0; i < s.length(); i++)
			emit(s.charAt(i));
	}
	public final void emit(String s, CclibSource source) {
		locate(source); emit(s);
	}
}
